#pragma once

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>  //或者使用json格式
// json 格式的序列化和反序列化

#define MySelf  1

//序列化和反序列化

const std::string blank_space_sep = " ";
const std::string protocol_sep = "\n";


//序列化添加报头和报尾 编码添加报头包尾
// "len"\n"x op y"\nXXXXXX
std::string Encode(std::string &content)
{
    std::string package = std::to_string(content.size());
    package += protocol_sep;
    package += content;
    package += protocol_sep;

    return package;
}

//解码 解码报头和报尾
// "len"\n"x op y"\nXXXXXX ----> "x op y"
bool Decode(std::string& package, std::string* content)
{
    //解析报头和报尾"protocolnumber"\n"len"\n"x op y"\nXXXXXX
    std::size_t pos = package.find(protocol_sep);
    if (pos == std::string::npos)
         return false;
    
    std::string len_str = package.substr(0, pos);
    std::size_t len = std::stoi(len_str);

    //len +"\n" "x + y" +"\n"
    std::size_t total_len = len_str.size() + len + 2;
    if(package.size() < total_len) 
        return false;

    *content = package.substr(pos+1, len);
    //移除报文
    package.erase(0, total_len);

    return true;
}

//发过来的报文 自己定义 将值 序列化成 "x + y"
class Request
{
public:
    Request(int data1, int data2, char oper) : x(data1), y(data2), op(oper) {}
    Request() {}

    ~Request() {}

public:
    //是否序列化成功
    bool Serialize(std::string *out)
    {
#ifdef MySelf
        //构建报文有效载荷
        //out ---> " x + y"
        std::string s = std::to_string(x);
        s += blank_space_sep;
        s += op;
        s += blank_space_sep;
        s += std::to_string(y);
        *out = s;
        return true;
#else
        //使用 json 格式的序列化
        Json::Value root;
        root["x"] = x;
        root["y"] = y;
        root["op"] = op;
            
        Json::StyledWriter w;
        *out = w.write(root);
        return true;
#endif
    }
    
    bool Deserialize(const std::string& in)
    {
#ifdef MySelf
        // "x + y"
        std::size_t left = in.find(blank_space_sep);
        if(left == std::string::npos)
            return false;

        std::string partx = in.substr(0, left);

        std::size_t right = in.rfind(blank_space_sep);
        if(right == std::string::npos)
            return false;

        std::string party = in.substr(right + 1);
        
        //同时在判断一下是中间有无多余的空格
        if(left + 2 != right)
            return false;
        
        //赋值
        op = in[left + 1];
        x = std::stoi(partx);
        y = std::stoi(party);
        return true; 
#else
        Json::Value root;
        Json::Reader r;
        r.parse(in, root);

        x = root["x"].asInt();
        y = root["y"].asInt();
        op = root["op"].asInt();
        return true;
#endif    
    }

    void DebugPrint()
    {
        std::cout << "新请求构建完成:  " << x << op << y << "=?" << std::endl;
    }


public:
    //x op y
    int x;
    int y;
    char op;
};


//回答 result code
class Response
{
public:
    Response(int res, int c) :result(res), code(c) {}
    Response() {}
    ~Response() {}
public:
    //序列化
    bool Serialize(std::string *out)
    {
#ifdef MySelf
        //构建报文有效载荷
        //out ---> "result code"
        std::string s = std::to_string(result);
        s += blank_space_sep;
        s += std::to_string(code);
        *out = s;
        return true;
#else
        Json::Value root;
        root["result"] = result;
        root["code"] = code;
        // Json::FastWriter w;
        Json::StyledWriter w;
        *out = w.write(root);
        return true;
#endif
    }

    //反序列化
    bool Deserialize(const std::string &in) // "x op y"
    {
#ifdef MySelf
        std::size_t pos = in.find(blank_space_sep);
        if (pos == std::string::npos)
            return false;

        std::string part_left = in.substr(0, pos);
        std::string part_right = in.substr(pos + 1);

        result = std::stoi(part_left);
        code = std::stoi(part_right);

        return true;
#else
        Json::Value root;
        Json::Reader r;
        r.parse(in, root);

        result = root["result"].asInt();
        code = root["code"].asInt();
        return true;
#endif
    }

    void DebugPrint()
    {
        std::cout << "结果响应完成, result: " << result << ", code: "<< code << std::endl;
    }
public:
    int result;
    int code; // 0，可信，否则!0具体是几，表明对应的错误原因
};
